import * as THREE from 'three';
import RippleGen from './rippleGen';
import * as utils from '../utils';
import fragShader from '../GLSL/fragShader'
import vertShader from '../GLSL/vertShader'

export default class Grid {
    constructor(_scene, _renderer) {
        console.log('波浪方格类')
        this.GRID_SIZE = 32;
        this.GRID_HALFSIZE = this.GRID_SIZE / 2;
        this.parent = _scene;
        this.prevOrigin = new THREE.Vector2();
        this.ripplePos = new THREE.Vector2();
        this.rippleGen = new RippleGen(_renderer, this.ripplePos, this.GRID_SIZE); // 新建波浪
        this.generateGrid(); // 生成方格
    }
    generateGrid () {
        ///////////////// GRID MATERIAL /////////////////
        this.ledSprite = new THREE.TextureLoader().load("/dist/images/3d/textures/ledA.png"); // 加载方格素材图片
        this.color = new THREE.Color(0xffffff); // 设置方格颜色
        // 使用自定义shader 用GPU渲染的材质
        this.gridMaterial = new THREE.ShaderMaterial({
            uniforms: {
                led: { value: this.ledSprite },
                heightmap: { value: null },
                vpH: { value: window.innerHeight },
                prog: { value: 0.0 },
                origin: { value: new THREE.Vector2() },
                color: { value: this.color }
            },
            defines: {
                RANGE: (this.GRID_SIZE / 2).toFixed(1),
                RANGE2: (this.GRID_SIZE).toFixed(1)
            },
            vertexShader: vertShader,
            fragmentShader: fragShader,
            transparent: true,
            depthWrite: false // 渲染此材质的时候，对深度缓冲区没有任何的影响
        });
        this.uniProgress = this.gridMaterial.uniforms["prog"];
        
        this.uniOrigin = this.gridMaterial.uniforms["origin"];
        ///////////////// GRID GEOMETRY /////////////////
        let vertCount = Math.pow(this.GRID_SIZE, 2);
        let position = new Float32Array(vertCount * 3);
        let uvs = new Float32Array(vertCount * 2);
        let diagonal = new Uint16Array(vertCount);
        let randI = THREE.Math.randInt;
        let xPos = 0;
        let zPos = 0;
        for (let i = 0, i3 = 0; i < vertCount; i++, i3 += 3) {

            xPos = (i % this.GRID_SIZE);
            zPos = Math.floor(i / this.GRID_SIZE);
            position[i3 + 0] = xPos - this.GRID_HALFSIZE;
            position[i3 + 1] = 0;
            position[i3 + 2] = zPos - this.GRID_HALFSIZE;
            uvs[i * 2 + 0] = xPos / this.GRID_SIZE;
            uvs[i * 2 + 1] = 1.0 - zPos / this.GRID_SIZE;
            diagonal[i] = (xPos + zPos) % 2;
        }
        this.geometry = new THREE.BufferGeometry();
        this.geometry.setAttribute("position", new THREE.BufferAttribute(position, 3));
        this.geometry.setAttribute("uv", new THREE.BufferAttribute(uvs, 2));
        this.geometry.setAttribute("diagonal", new THREE.BufferAttribute(diagonal, 1));
        ///////////////// GRID OBJECT /////////////////
        this.lightGrid = new THREE.Points(this.geometry, this.gridMaterial);
        this.lightGrid.frustumCulled = false;
        this.parent.add(this.lightGrid);
    };
    moveRippleOrigin (_x, _y) {
        this.ripplePos.set(_x, _y);
    };
    ///////////////////////////// PUBLIC METHODS /////////////////////////////
    // 将方格变成黑色
    goToBlackGrid () {
        TweenLite.to(this.color, 1.0, { r: 0.0, g: 0.0, b: 0.0, easing: Power2.easeInOut });
        TweenLite.to(this.uniProgress, 1.0, { value: 0.0, easing: Power2.easeInOut });
    };
    update (_props) {
        if (typeof _props != "undefined" && _props.speed > 0) {
            this.rippleGen.newRippleImpact(_props.speed / 64);
            this.moveRippleOrigin(utils.mod((_props.pos.x + this.GRID_HALFSIZE), this.GRID_SIZE) - this.GRID_HALFSIZE, utils.mod((_props.pos.y + this.GRID_HALFSIZE), this.GRID_SIZE) - this.GRID_HALFSIZE);
            this.uniOrigin.value = _props.pos;
        }
        this.gridMaterial.uniforms["heightmap"].value = this.rippleGen.update();
        this.moveRippleOrigin(1000, 1000);
    };
    // On Window Resize
    onWindowResize (vpW, vpH, pixelRatio) {
        this.gridMaterial.uniforms["vpH"].value = vpH * pixelRatio;
    };
}